﻿using System.Collections;
using System.Collections.Generic;

namespace Jinndev {

    /// <summary>
    /// 双向Map，可通过key和value互相查询
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    public class BiMap<K, V> : IReadOnlyCollection<KeyValuePair<K, V>> {

        private Dictionary<K, V> kvDict;
        private Dictionary<V, K> vkDict;

        public BiMap() {
            kvDict = new Dictionary<K, V>();
            vkDict = new Dictionary<V, K>();
        }

        public BiMap(int capacity) {
            kvDict = new Dictionary<K, V>(capacity);
            vkDict = new Dictionary<V, K>(capacity);
        }

        public Dictionary<K, V>.KeyCollection Keys {
            get { return kvDict.Keys; }
        }

        public Dictionary<K, V>.ValueCollection Values {
            get { return kvDict.Values; }
        }

        public bool Add(K key, V value) {
            if (kvDict.ContainsKey(key) || vkDict.ContainsKey(value)) {
                return false;
            }
            kvDict.Add(key, value);
            vkDict.Add(value, key);
            return true;
        }

        public bool TryGetKey(V value, out K key) {
            return vkDict.TryGetValue(value, out key);
        }

        public bool TryGetValue(K key, out V value) {
            return kvDict.TryGetValue(key, out value);
        }

        public bool RemoveKey(K key) {
            if (kvDict.TryGetValue(key, out V value)) {
                kvDict.Remove(key);
                vkDict.Remove(value);
                return true;
            }
            return false;
        }

        public bool RemoveValue(V value) {
            if (vkDict.TryGetValue(value, out K key)) {
                kvDict.Remove(key);
                vkDict.Remove(value);
                return true;
            }
            return false;
        }

        public int Count => kvDict.Count;

        public void Clear() {
            kvDict.Clear();
            vkDict.Clear();
        }

        public IEnumerator<KeyValuePair<K, V>> GetEnumerator() {
            return kvDict.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

    }

}